﻿var COK = {};

COK.convertData = function (value, type, fallbackValue) {

    if (!fallbackValue) {
        fallbackValue = null;
    }

    switch (type) {
        case COK.PropertyDataType.AUTO: {
            return value;
        }
        case COK.PropertyDataType.STRING: {
            return value.toString();
        }
        case COK.PropertyDataType.BOOL: {
            if (value.toString().toLowerCase() == "true" || value == true || value == 1 || value == "1") {
                return true;
            }

            if (value.toString().toLowerCase() == "false" || value == false || value == 0 || value == "0") {
                return false;
            }

            return fallbackValue;
        }
        case COK.PropertyDataType.INT: {
            value = Number(value);
            if (!isNaN(value)) {
                return parseInt(value);
            } else {
                return fallbackValue;
            }
        }
        case COK.PropertyDataType.FLOAT: {
            value = Number(value);
            if (!isNaN(value)) {
                return parseFloat(value);
            } else {
                return fallbackValue;
            }
        }
        case COK.PropertyDataType.DATETIME: {

            var floatValue = Number(value);

            if (!isNaN(floatValue) && Number.isFinite(floatValue)) {
                return new Date((floatValue - 25569) * 86400000); // OADate to JavaScript Date
            } else {
                var dateValue = new Date(value);
                if (!isNaN(dateValue.getTime())) {
                    return dateValue;
                }
            }

            return fallbackValue;
        }
    }
    return value;
};

COK.PropertyDataType = {
    AUTO: 0,
    STRING: 1,
    BOOL: 2,
    INT: 3,
    FLOAT: 4,
    DATETIME: 5
}

COK.returnToParam = function (OutParamaterName, data) {

    if (OutParamaterName && OutParamaterName != "") {
        console.log("The value " + JSON.stringify(data) + " was set to [" + OutParamaterName + "]");
        Forguncy.CommandHelper.setVariableValue(OutParamaterName, data);
    } else {
        console.error("The OutParamaterName was not set, the value is: " + JSON.stringify(data));
    }
};

COK.getPropertyValue = function (target, pName) {

    if (target == null || target == undefined) {
        return null;
    }

    if (!pName || pName.toLowerCase() === "%value%") {
        return target;
    } else {
        return target[pName];
    }
}


var ClientSideArrayOp = (function (_super) {
    __extends(ClientSideArrayOp, _super);
    function ClientSideArrayOp() {
        return _super !== null && _super.apply(this, arguments) || this;
    }


    ClientSideArrayOp.prototype.execute = function () {

        var params = this.CommandParam;
        var Operation = params.Operation;
        var inP = this.evaluateFormula(params.InParamaterName);
        var paramA = this.evaluateFormula(params.OperationParamaterAName);
        var paramB = this.evaluateFormula(params.OperationParamaterBName);
        var OutParamaterName = params.OutParamaterName;
        var OutParamaterName2 = params.OutParamaterName2;

        switch (Operation) {
            case SupportedOperations.Create: {
                COK.returnToParam(OutParamaterName, []);

                break;
            }
            case SupportedOperations.Set: {

                if (!Array.isArray(inP)) {

                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (isNaN(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be a number.");
                    return;
                }
                paramA = parseInt(paramA);

                inP[paramA] = paramB;
                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Get: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (isNaN(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be a number.");
                    return;
                }

                paramA = parseInt(paramA);

                COK.returnToParam(OutParamaterName, inP[paramA]);
                break;
            }
            case SupportedOperations.Length: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                COK.returnToParam(OutParamaterName, inP.length);
                break;
            }
            case SupportedOperations.Push: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                inP.push(paramA);

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Pop: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                var result = inP.pop();

                COK.returnToParam(OutParamaterName, result);
                break;
            }
            case SupportedOperations.Unshift: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                inP.unshift(paramA);

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Shift: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                var result = inP.shift();

                COK.returnToParam(OutParamaterName, result);
                COK.returnToParam(OutParamaterName2, inP);
                break;
            }
            case SupportedOperations.Concat: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (!Array.isArray(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be an Array.");
                    return;
                }

                this.log("提示：Concat操作不会对两个数组产生影响，而是生成一个新数组。如需将一个数组加入另一个数组中，请使用InsertRange操作。");
                var result = inP.concat(paramA);

                COK.returnToParam(OutParamaterName, result);
                break;
            }
            case SupportedOperations.Slice: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (isNaN(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be a number.");
                    return;
                }

                if (isNaN(paramB)) {
                    this.log("Paramater [" + params.OperationParamaterBName + "] should be a number.");
                    return;
                }

                paramA = parseInt(paramA);
                paramB = parseInt(paramB);

                var result = inP.slice(paramA, paramB);

                COK.returnToParam(OutParamaterName, result);
                break;
            }
            case SupportedOperations.InsertRange: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (!Array.isArray(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be an Array.");
                    return;
                }

                if (isNaN(paramB)) {
                    this.log("Paramater [" + params.OperationParamaterBName + "] should be a number.");
                    return;
                }
                paramB = parseInt(paramB);

                var sub = paramA.concat();

                for (var i1 = 0; i1 < sub.length; i1++) {
                    inP.splice(paramB + i1, 0, sub[i1]);
                }

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.RemoveRange: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (isNaN(paramA)) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be a number.");
                    return;
                }


                if (isNaN(paramB)) {
                    this.log("Paramater [" + params.OperationParamaterBName + "] should be a number.");
                    return;
                }

                paramA = parseInt(paramA);
                paramB = parseInt(paramB);

                var removedItem = inP.splice(paramA, paramB);

                COK.returnToParam(OutParamaterName, removedItem);
                COK.returnToParam(OutParamaterName2, inP);
                break;
            }
            case SupportedOperations.Split: {
                var result = paramB.split(paramA);
                COK.returnToParam(OutParamaterName, result);
                break;
            }
            case SupportedOperations.IndexOf: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                var index = inP.indexOf(paramA);

                COK.returnToParam(OutParamaterName, index);
                break;
            }
            case SupportedOperations.LastIndexOf: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                var index = inP.lastIndexOf(paramA);

                COK.returnToParam(OutParamaterName, index);
                break;
            } case SupportedOperations.FromJSON: {
                var arr = JSON.parse(paramA);
                if (arr && Array.isArray(arr)) {
                    COK.returnToParam(OutParamaterName, arr);
                } else {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should be a JSON string of Array.");
                }

                break;
            }
            case SupportedOperations.ToJSON: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                COK.returnToParam(OutParamaterName, JSON.stringify(inP));
                break;
            }
            case SupportedOperations.Join: {

                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                var values = [];

                for (var i1 = 0; i1 < inP.length; i1++) {

                    if (inP[i1] != undefined && inP[i1] != null) {

                        var value = COK.getPropertyValue(inP[i1], paramB);
                        if (value == null || value == undefined) {
                            value = "null";
                        }

                        values.push(value);

                    } else {
                        values.push("null")
                    }

                }

                COK.returnToParam(OutParamaterName, values.join(paramA));
                break;
            }
            case SupportedOperations.Select: {
                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }

                if (!paramA) {
                    this.log("Paramater [" + params.OperationParamaterAName + "] should not be null.");
                    return;
                }

                var values = [];

                inP.map(function (obj) {

                    var value = COK.getPropertyValue(obj, paramA);

                    values.push(value);
                });

                COK.returnToParam(OutParamaterName, values);
                break;
            }
            case SupportedOperations.Distinct: {
                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamaterName + "] should be an Array.");
                    return;
                }
                var taken = [];
                var values = [];

                inP.map(function (obj) {

                    var key;

                    if (obj) {
                        var prop = COK.getPropertyValue(obj, paramA);

                        if (prop === undefined) {
                            key = "propertyUndefined";
                        } else if (prop === null) {
                            key = "propertyNull";
                        } else {
                            key = JSON.stringify(prop);
                        }
                    }

                    if (taken.indexOf(key) < 0) {
                        taken.push(key);
                        values.push(obj);
                    }
                });

                COK.returnToParam(OutParamaterName, values);

                break;
            }
        }

    };

    var SupportedOperations = {
        Create: 0,
        Set: 1,
        Get: 2,
        Length: 3,
        Push: 4,
        Pop: 5,
        Unshift: 6,
        Shift: 7,
        Concat: 8,
        Slice: 9,
        InsertRange: 10,
        RemoveRange: 11,
        IndexOf: 12,
        LastIndexOf: 13,
        FromJSON: 14,
        ToJSON: 15,
        Join: 16,
        Split: 17,
        Select: 18,
        Distinct: 19

    }

    return ClientSideArrayOp;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideArrayOp, CollectionOperationKit", ClientSideArrayOp);


var ClientSideStringMapOp = (function (_super) {
    __extends(ClientSideStringMapOp, _super);
    function ClientSideStringMapOp() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideStringMapOp.prototype.tryCastToObject = function (inP) {

        if (inP instanceof Map) {
            return Object.fromEntries(inP);
        } else if (inP instanceof Object) {
            return inP;
        } else {
            this.log("Paramater (" + inP + ") should be an Map or Object.");
            return {};
        }
    };

    ClientSideStringMapOp.prototype.execute = function () {
        var params = this.CommandParam;
        var Operation = params.Operation;
        var inP = this.evaluateFormula(params.InParamater);
        var pKey = this.evaluateFormula(params.OperationParamaterKey);
        var pValue = this.evaluateFormula(params.OperationParamaterValue);
        var OutParamaterName = params.OutParamaterName;

        switch (Operation) {
            case SupportedOperations.Create: {
                COK.returnToParam(OutParamaterName, new Object());
                break;
            }
            case SupportedOperations.Clear: {

                inP = this.tryCastToObject(inP);

                inP = {};
                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Set: {
                inP = this.tryCastToObject(inP);

                inP[pKey] = pValue;
                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Has: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, inP.hasOwnProperty(pKey) ? 1 : 0);
                break;
            }
            case SupportedOperations.Get: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, inP.hasOwnProperty(pKey) ? inP[pKey] : pValue);
                break;
            }
            case SupportedOperations.Size: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, Object.keys(inP).length);
                break;
            }
            case SupportedOperations.Delete: {
                inP = this.tryCastToObject(inP);

                if (inP.hasOwnProperty(pKey)) {
                    delete inP[pKey];
                }

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Keys: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, Array.from(Object.keys(inP)));
                break;
            }
            case SupportedOperations.Values: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, Array.from(Object.values(inP)));
                break;
            }
            case SupportedOperations.FromObject: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.ToObject: {
                inP = this.tryCastToObject(inP);

                COK.returnToParam(OutParamaterName, inP);
                break;
            }


        }

    };

    var SupportedOperations = {
        Create: 0,
        Get: 1,
        Set: 2,
        Has: 3,
        Delete: 4,
        Clear: 5,
        Size: 6,
        Keys: 7,
        Values: 8,
        FromObject: 9,
        ToObject: 10
    }

    return ClientSideStringMapOp;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideStringMapOp, CollectionOperationKit", ClientSideStringMapOp);

var ClientSideObjectOp = (function (_super) {
    __extends(ClientSideObjectOp, _super);
    function ClientSideObjectOp() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideObjectOp.prototype.execute = function () {
        var params = this.CommandParam;
        var Operation = params.Operation;
        var PropPairs = params.OperationParamaterPairs;
        var inP = this.evaluateFormula(params.InParamater);
        var pName = this.evaluateFormula(params.OperationParamaterName);
        var pValue = this.evaluateFormula(params.OperationParamaterValue);
        var pType = this.evaluateFormula(params.OperationParamaterValueType);
        var OutParamaterName = params.OutParamaterName;

        switch (Operation) {
            case SupportedOperations.Create: {
                var inP = new Object();

                if (PropPairs && PropPairs instanceof Array) {
                    var me = this;

                    PropPairs.forEach(function (v) {
                        var pNameP = me.evaluateFormula(v.Name);
                        var pValueP = me.evaluateFormula(v.Value);
                        var pValueT = me.evaluateFormula(v.DataType);

                        inP[pNameP] = COK.convertData(pValueP, pValueT);
                    });
                }

                COK.returnToParam(OutParamaterName, inP);

                break;
            }
            case SupportedOperations.Null: {
                if (!inP instanceof Object) {
                    this.log("Paramater [" + params.InParamater + "] should be an Object.");
                    return;
                }

                inP = null;
                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.Properties: {
                if (!inP instanceof Object) {
                    this.log("Paramater [" + params.InParamater + "] should be an Object.");
                    return;
                }

                var pops = [];

                for (pop in inP) {
                    pops.push(pop);
                }

                COK.returnToParam(OutParamaterName, pops);
                break;
            }
            case SupportedOperations.GetPropertyValue: {
                if (!inP instanceof Object) {
                    this.log("Paramater [" + params.InParamater + "] should be an Object.");
                    return;
                }

                for (pop in inP) {
                    if (pop === pName) {
                        COK.returnToParam(OutParamaterName, inP[pop]);
                        return;
                    }
                }

                COK.returnToParam(OutParamaterName, pValue);
                break;
            }
            case SupportedOperations.SetPropertyValue: {
                if (!inP instanceof Object) {
                    this.log("Paramater [" + params.InParamater + "] should be an Object.");
                    return;
                }

                inP[pName] = COK.convertData(pValue, pType);

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
            case SupportedOperations.SetProperties: {
                if (!inP instanceof Object) {
                    this.log("Paramater [" + params.InParamater + "] should be an Object.");
                    return;
                }

                if (!PropPairs || !PropPairs instanceof Array) {
                    this.log("Paramater [OperationParamaterPairs] was not set.");
                    return;
                }

                var me = this;

                PropPairs.forEach(function (v) {
                    var pNameP = me.evaluateFormula(v.Name);
                    var pValueP = me.evaluateFormula(v.Value);
                    var pValueT = me.evaluateFormula(v.DataType);

                    inP[pNameP] = COK.convertData(pValueP, pValueT);
                });

                COK.returnToParam(OutParamaterName, inP);
                break;
            }
        }

    };

    var SupportedOperations = {
        Create: 0,
        Properties: 1,
        GetPropertyValue: 2,
        SetPropertyValue: 3,
        SetProperties: 4,
        Null: 5
    }

    return ClientSideObjectOp;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideObjectOp, CollectionOperationKit", ClientSideObjectOp);

var ClientSideQueryOp = (function (_super) {
    __extends(ClientSideQueryOp, _super);
    function ClientSideQueryOp() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideQueryOp.prototype.checkWithConditions = function (target, conditions) {

        if (conditions === null || conditions === undefined || conditions.length === 0) {

            return true;
        }

        if (conditions instanceof Array) {
            var me = this;

            for (j = 0; j < conditions.length; j++) {
                var v = conditions[j];

                var pName = me.evaluateFormula(v.Name);
                var pValue = me.evaluateFormula(v.Value);

                var value = COK.getPropertyValue(target, pName);

                switch (v.Op) {
                    case CalcOp.等于: {
                        if (!(value == pValue || (value == null && pValue == "%null%"))) return false;
                        break;
                    }
                    case CalcOp.不等于: {
                        if (value == pValue || (value == null && pValue == "%null%")) return false;
                        break;
                    }
                    case CalcOp.包含字符串: {
                        if (typeof value == 'string') {
                            if (value.indexOf(pValue) == -1) return false;
                            break;
                        } else {
                            return false;
                        }
                    }
                    case CalcOp.不包含字符串: {
                        if (typeof value == 'string') {
                            if (value.indexOf(pValue) >= 0) return false;
                            break;
                        } else {
                            return false;
                        }
                    }
                    case CalcOp.开头是: {
                        if (typeof value == 'string') {
                            if (value.indexOf(pValue) != 0) return false;
                            break;
                        } else {
                            return false;
                        }
                    }
                    case CalcOp.开头不是: {
                        if (typeof value == 'string') {
                            if (value.indexOf(pValue) == 0) return false;
                            break;
                        } else {
                            return false;
                        }
                    }
                    case CalcOp.大于: {
                        if (!(value > pValue)) return false;
                        break;
                    }
                    case CalcOp.不大于: {
                        if (value > pValue) return false;
                        break;
                    }
                    case CalcOp.小于: {
                        if (!(value < pValue)) return false;
                        break;
                    }
                    case CalcOp.不小于: {
                        if (value < pValue) return false;
                        break;
                    }
                }

            }

            return true;
        } else {
            this.log("Query condition was not an array. The condition's type is " + typeof inP);
            return false;
        }
    };

    ClientSideQueryOp.prototype.execute = function () {
        var params = this.CommandParam;
        var Operation = params.Operation;
        var PropPairs = params.OperationParamaterPairs;
        var inP = this.evaluateFormula(params.InParamater);
        var OutParamaterName = params.OutParamaterName;

        switch (Operation) {
            case SupportedOperations.Where: {
                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamater + "] should be an Array: " + typeof inP);
                    return;
                }
                var me = this;
                var result = [];

                inP.forEach(function (v) {
                    if (me.checkWithConditions(v, PropPairs)) {
                        result.push(v);
                    }
                });

                COK.returnToParam(OutParamaterName, result);

                break;
            }
            case SupportedOperations.First: {
                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamater + "] should be an Array: " + typeof inP);
                    return;
                }
                var result;

                for (i = 0; i < inP.length; i++) {
                    var v = inP[i];
                    if (this.checkWithConditions(v, PropPairs)) {
                        result = v;
                        break;
                    }
                }

                COK.returnToParam(OutParamaterName, result);

                break;
            }

            case SupportedOperations.Last: {
                if (!Array.isArray(inP)) {
                    this.log("Paramater [" + params.InParamater + "] should be an Array: " + typeof inP);
                    return;
                }
                var me = this;
                var result;

                inP.forEach(function (v) {
                    if (me.checkWithConditions(v, PropPairs)) {
                        result = v;
                    }
                });

                COK.returnToParam(OutParamaterName, result);

                break;
            }

        }

    };

    var SupportedOperations = {
        Where: 0,
        First: 1,
        Last: 2
    }

    var CalcOp = {
        等于: 0,
        不等于: 1,
        大于: 2,
        不大于: 3,
        小于: 4,
        不小于: 5,
        包含字符串: 6,
        不包含字符串: 7,
        开头是: 8,
        开头不是: 9
    }

    return ClientSideQueryOp;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideQueryOp, CollectionOperationKit", ClientSideQueryOp);

var ClientSideArraySort = (function (_super) {
    __extends(ClientSideArraySort, _super);
    function ClientSideArraySort() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideArraySort.prototype.execute = function () {
        var params = this.CommandParam;
        var PropPairs = params.SortRulePairs;
        var inP = this.evaluateFormula(params.InParamater);
        var OutParamaterName = params.OutParamaterName;
        var result = inP;

        var me = this;

        if (PropPairs && Array.isArray(PropPairs)) {

            PropPairs.reverse().forEach((rule) => {

                result = result.sort(function (left, right) {
                    var leftV = COK.getPropertyValue(left, me.evaluateFormula(rule.Name));
                    var rightV = COK.getPropertyValue(right, me.evaluateFormula(rule.Name));

                    if (leftV == rightV) {
                        return 0;
                    } else if (leftV > rightV) {
                        return (rule.Direction == SupportedDirection.Asc) ? 1 : -1;
                    } else {
                        return (rule.Direction == SupportedDirection.Asc) ? -1 : 1;
                    }

                });
            });
        }

        COK.returnToParam(OutParamaterName, result);
    };

    var SupportedDirection = {
        Asc: 0,
        Desc: 1
    }


    return ClientSideArraySort;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideArraySort, CollectionOperationKit", ClientSideArraySort);


var ClientSideDataConvert = (function (_super) {
    __extends(ClientSideDataConvert, _super);
    function ClientSideDataConvert() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideDataConvert.prototype.execute = function () {
        var params = this.CommandParam;
        var OperationParamaterValueType = params.OperationParamaterValueType;
        var OutParamaterName = params.OutParamaterName;
        var inP = this.evaluateFormula(params.InParamater);
        var defaultP = this.evaluateFormula(params.DefaultParamater);
        var nullP = this.evaluateFormula(params.NullValueParamater);

        if (inP == null || inP == undefined) {
            var result = COK.convertData(nullP, OperationParamaterValueType, defaultP);

            COK.returnToParam(OutParamaterName, result);

        } else {
            var result = COK.convertData(inP, OperationParamaterValueType, defaultP);

            COK.returnToParam(OutParamaterName, result);
        }

    };



    return ClientSideDataConvert;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideDataConvert, CollectionOperationKit", ClientSideDataConvert);


var ClientSideArrayCalc = (function (_super) {
    __extends(ClientSideArrayCalc, _super);
    function ClientSideArrayCalc() {
        return _super !== null && _super.apply(this, arguments) || this;
    }

    ClientSideArrayCalc.prototype.execute = function () {
        var params = this.CommandParam;
        var Operation = params.Operation;
        var inP = this.evaluateFormula(params.InParamater);
        if (!Array.isArray(inP)) {
            this.log("Paramater [" + params.InParamater + "] should be an Array.");
            return;
        }

        var propName = this.evaluateFormula(params.OperationFieldName);
        var OutParamaterName = params.OutParamaterName;

        switch (Operation) {
            case SupportedOperations.SUM: {

                var result = inP.reduce(function (sum, item) {
                    var value = COK.getPropertyValue(item, propName);

                    if (value === null || value === undefined) {
                        return sum;
                    }

                    if (typeof value === "number") {
                        return sum + value;
                    } else if (!isNaN(value)) {
                        return sum + parseFloat(value);
                    } else {
                        return sum;
                    }
                }, 0);

                COK.returnToParam(OutParamaterName, result);
                break;
            }
            case SupportedOperations.AVG: {

                if (inP.length === 0) {
                    COK.returnToParam(OutParamaterName, null);
                } else {

                    var sum = inP.reduce(function (sum, item) {
                        var value = COK.getPropertyValue(item, propName);

                        if (value === null || value === undefined) {
                            return sum;
                        }

                        if (typeof value === "number") {
                            return sum + value;
                        } else if (!isNaN(value)) {
                            return sum + parseFloat(value);
                        } else {
                            return sum;
                        }
                    }, 0);

                    var count = inP.reduce(function (count, item) {
                        var value = COK.getPropertyValue(item, propName);

                        if (value === null || value === undefined) {
                            return count;
                        }

                        if (value !== null && value !== undefined) {
                            return count + 1;
                        } else {
                            return count;
                        }
                    }, 0);

                    COK.returnToParam(OutParamaterName, (count == 0) ? 0 : sum / count);
                }
                break;
            }
            case SupportedOperations.MAX: {

                if (inP.length === 0) {
                    COK.returnToParam(OutParamaterName, null);
                }
                else {

                    var result = inP.reduce(function (max, item) {
                        var value = COK.getPropertyValue(item, propName);

                        if (value === null || value === undefined) {
                            return max;
                        }

                        if (typeof value === "number") {
                            return Math.max(max, value);
                        } else if (!isNaN(value)) {
                            return Math.max(max, parseFloat(value));
                        } else {
                            return max;
                        }
                    }, -Infinity);
                    COK.returnToParam(OutParamaterName, result);
                }
                break;
            }
            case SupportedOperations.MIN: {

                if (inP.length === 0) {
                    COK.returnToParam(OutParamaterName, null);
                } else {
                    var result = inP.reduce(function (min, item) {
                        var value = COK.getPropertyValue(item, propName);

                        if (value === null || value === undefined) {
                            return min;
                        }

                        if (typeof value === "number") {
                            return Math.min(min, value);
                        } else if (!isNaN(value)) {
                            return Math.min(min, parseFloat(value));
                        } else {
                            return min;
                        }
                    }, Infinity);
                    COK.returnToParam(OutParamaterName, result);
                }
                break;
            }
            case SupportedOperations.COUNT: {

                var result = inP.reduce(function (count, item) {
                    var value = COK.getPropertyValue(item, propName);
                    if (value !== null && value !== undefined) {
                        return count + 1;
                    } else {
                        return count;
                    }
                }, 0);

                COK.returnToParam(OutParamaterName, result);
                break;
            }
        }

    };

    var SupportedOperations = {
        SUM: 0,
        COUNT: 1,
        AVG: 2,
        MAX: 3,
        MIN: 4
    }

    return ClientSideArrayCalc;
}(Forguncy.CommandBase));


Forguncy.CommandFactory.registerCommand("CollectionOperationKit.ClientSideArrayCalc, CollectionOperationKit", ClientSideArrayCalc);